import StageBase from "./StageBase";
import ScreenFit from "../ScreenFit";
import CommonUtils from "../CommonUtils";
import App from "./App";

export enum SwapMethod {
    None = 1,
    WhiteFade,
    BlackFade,
    Mark
}

/**
 * 场景切换管理器，支持场景内界面切换样式和场景间间切换样式
 */
export default class SceneManager {

    static Event_StageIn = "Event_StageIn";
    static Event_StageOut = "Event_StageOut";
    static currSceneName: string;
    static currStage: any;

    /**
     * 场景内界面切换
     */
    static swapToStage(toStage: any, method: SwapMethod = SwapMethod.None, duration: number = 0.5, closePrevious: boolean = true) {
        SceneManager.doSwapToStage(toStage, method, duration, closePrevious, false);
    }

    /** 重载当前场景 */
    static reloadCurrStage(method: SwapMethod = SwapMethod.None) {
        SceneManager.doSwapToStage(SceneManager.currStage, method, 0.5, true, true);
    }

    private static doSwapToStage(toStageClass: any, method: SwapMethod, duration: number, closePrevious: boolean, canReload: boolean) {
        if (!canReload && SceneManager.currStage == toStageClass) {
            console.error('当前已经在此Stage：' + toStageClass);
            return;
        }
        if (method == SwapMethod.Mark && !SceneManager.currStage) {
            console.error('currStage为null，无法使用SwapMethod.Mark方式转场');
            method = SwapMethod.None;
        }
        let stagePrefab = App.instance.resPreloader.getRes('prefabs/stages/' + cc.js.getClassName(toStageClass)) as cc.Prefab;
        let toStage: StageBase = cc.instantiate(stagePrefab).getComponent(StageBase);
        cc.Canvas.instance.node.addChild(toStage.node);
        toStage.node.active = false;
        switch (method) {
            case SwapMethod.None:
                if (closePrevious && SceneManager.currStage) {
                    if (SceneManager.currStage.node) {
                        SceneManager.currStage.node.destroy();
                    }
                }
                SceneManager.currStage = toStage;
                toStage.node.active = true;
                break;
            case SwapMethod.WhiteFade:
            case SwapMethod.BlackFade:
                let whiteNode = new cc.Node('WhiteBoard');
                CommonUtils.setTouchMask(whiteNode);
                whiteNode.addComponent(cc.Sprite).spriteFrame = App.instance.resPreloader.getRes('textures/common/white2x2') as cc.SpriteFrame;
                whiteNode.width = ScreenFit.screenSize.width;
                whiteNode.height = ScreenFit.screenSize.height;
                if (method == SwapMethod.BlackFade) {
                    whiteNode.color = cc.color(0, 0, 0);
                }
                App.instance.node.addChild(whiteNode);
                let d = 0;
                if (SceneManager.currStage) {
                    whiteNode.opacity = 0;
                    d = duration;
                }
                cc.tween(whiteNode).to(d, { opacity: 255 }).call(() => {
                    if (closePrevious && SceneManager.currStage) {
                        if (SceneManager.currStage.node) {
                            SceneManager.currStage.node.destroy();
                        }
                    }
                    SceneManager.currStage = toStage;
                    toStage.node.active = true;
                    d = duration;
                    cc.tween(whiteNode).to(d, { opacity: 0 }).call(() => {
                        whiteNode.destroy();
                    }).start();
                }).start();
                break;
            case SwapMethod.Mark:
                let maskNode = new cc.Node('ScreenShotMark');
                cc.Canvas.instance.node.addChild(maskNode);
                CommonUtils.setTouchMask(maskNode);
                maskNode.width = maskNode.height = Math.max(ScreenFit.screenSize.width, ScreenFit.screenSize.height) * 1.3;
                let mask = maskNode.addComponent(cc.Mask);
                mask.type = cc.Mask.Type.ELLIPSE;
                SceneManager.currStage.node.setParent(maskNode);
                toStage.node.active = true;
                let previousStage = SceneManager.currStage;
                SceneManager.currStage = toStage;
                if (!duration) {
                    duration = 1;
                }
                cc.tween(maskNode).to(duration, { width: 0, height: 0 }).call(() => {
                    previousStage.node.setParent(cc.Canvas.instance.node);
                    if (closePrevious) {
                        previousStage.node.destroy();
                    } else {
                        previousStage.node.setSiblingIndex(toStage.node.getSiblingIndex() - 1);
                    }
                    maskNode.destroy();
                }).start();
                break;
        }
    }

    /**
     * 场景切换（样式待添加）
     * @param toSceneName 目标场景名称
     */
    static swapToScene(toSceneName: string, method: SwapMethod = SwapMethod.None, duration: number = 0.5) {
        if (SceneManager.currSceneName == toSceneName) {
            console.error('当前已经在此场景：' + toSceneName);
            return;
        }
        if (method == SwapMethod.Mark) {
            method = SwapMethod.BlackFade;
            console.error('场景跳转不支持遮罩样式');
        }
        switch (method) {
            case SwapMethod.None:
                cc.director.loadScene(toSceneName);
                SceneManager.currSceneName = toSceneName;
                SceneManager.currStage = null;
                break;
            case SwapMethod.WhiteFade:
            case SwapMethod.BlackFade:
                let whiteNode = new cc.Node('WhiteBoard');
                CommonUtils.setTouchMask(whiteNode);
                whiteNode.addComponent(cc.Sprite).spriteFrame = App.instance.resPreloader.getRes('textures/common/white2x2') as cc.SpriteFrame;
                whiteNode.width = ScreenFit.screenSize.width;
                whiteNode.height = ScreenFit.screenSize.height;
                if (method == SwapMethod.BlackFade) {
                    whiteNode.color = cc.color(0, 0, 0);
                }
                App.instance.node.addChild(whiteNode);
                whiteNode.opacity = 0;
                cc.tween(whiteNode).to(duration, { opacity: 255 }).call(() => {
                    if (SceneManager.currStage) {
                        if (SceneManager.currStage.node) {
                            SceneManager.currStage.node.destroy();
                        }
                    }
                    cc.director.loadScene(toSceneName, () => {
                        cc.tween(whiteNode).to(duration, { opacity: 0 }).call(() => {
                            whiteNode.destroy();
                        }).start();
                    });
                    SceneManager.currSceneName = toSceneName;
                    SceneManager.currStage = null;
                }).start();
                break;
        }
    }

    /** 当前场景是否是参数里的场景 */
    static isCurrStage(stage: any) {
        return cc.js.getClassName(this.currStage) == cc.js.getClassName(stage);
    }

}